๊ฒฌ๊ณ ํ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์ธํ๋ผ ๊ตฌ์ถ์ ๋ํ ์ฌ์ธต ๋ถ์์ผ๋ก, ์ต์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ ํ์ ๋๊ตฌ, ๋ชจ๋ฒ ์ฌ๋ก, ์์ ํ ๊ตฌํ ์ ๋ต์ ๋ค๋ฃน๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์ธํ๋ผ: ์ข ํฉ ๊ตฌํ ๊ฐ์ด๋
๋น ๋ฅด๊ฒ ๋ณํํ๋ ์น ๊ฐ๋ฐ ์ธ๊ณ์์, ํ์ฅ ๊ฐ๋ฅํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์ฐ๋ฉฐ ๊ณ ์ฑ๋ฅ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๊ธฐ ์ํด์๋ ๊ฒฌ๊ณ ํ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์ธํ๋ผ๊ฐ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ด ๊ฐ์ด๋๋ ํ์ ๋๊ตฌ, ๋ชจ๋ฒ ์ฌ๋ก, ๊ตฌํ ์ ๋ต์ ๋ค๋ฃจ๋ฉฐ ์ด๋ฌํ ์ธํ๋ผ๋ฅผ ์ค์ ํ๋ ์ ์ฒด ๊ณผ์ ์ ์๋ดํฉ๋๋ค. ์ฐ๋ฆฌ๋ ํจ์จ์ ์ธ ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ๋ฅผ ์ง์ํ๊ณ , ์ฝ๋ ํ์ง์ ๋ณด์ฅํ๋ฉฐ, ๋ฐฐํฌ ํ๋ก์ธ์ค๋ฅผ ๊ฐ์ํํ๋ ํ์คํ๋๊ณ ์๋ํ๋ ํ๊ฒฝ์ ๋ง๋๋ ๋ฐ ์ค์ ์ ๋ ๊ฒ์ ๋๋ค. ์ด ๊ฐ์ด๋๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ํ๋ก์ธ์ค๋ฅผ ๊ฐ์ ํ๊ณ ์ ํ๋ ๋ชจ๋ ์์ค์ ๊ฐ๋ฐ์๋ฅผ ๋์์ผ๋ก ํฉ๋๋ค. ๋ค์ํ ๊ธ๋ก๋ฒ ํ์ค ๋ฐ ๊ตฌ์ฑ์ ์ ์ฉ ๊ฐ๋ฅํ ์์ ๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค.
1. ํ๋ก์ ํธ ์ค์ ๋ฐ ์ด๊ธฐํ
1.1 ํ๋ก์ ํธ ๊ตฌ์กฐ ์ ํ
ํ๋ก์ ํธ ๊ตฌ์กฐ๋ ์ฝ๋๊ฐ ์ด๋ป๊ฒ ๊ตฌ์ฑ๋๋์ง๋ฅผ ๊ฒฐ์ ํ๋ฉฐ, ์ ์ง๋ณด์์ฑ๊ณผ ํ์ฅ์ฑ์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค. ๋ค์์ ๊ถ์ฅ๋๋ ๊ตฌ์กฐ์ ๋๋ค:
my-project/ โโโ src/ โ โโโ components/ โ โ โโโ Button.js โ โ โโโ Input.js โ โโโ utils/ โ โ โโโ api.js โ โ โโโ helpers.js โ โโโ App.js โ โโโ index.js โโโ public/ โ โโโ index.html โโโ tests/ โ โโโ Button.test.js โ โโโ Input.test.js โโโ .eslintrc.js โโโ .prettierrc.js โโโ webpack.config.js โโโ package.json โโโ README.md
์ค๋ช :
src/: ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ชจ๋ ์์ค ์ฝ๋๋ฅผ ํฌํจํฉ๋๋ค.components/: ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ UI ์ปดํฌ๋ํธ๋ฅผ ์ ์ฅํฉ๋๋ค.utils/: ์ ํธ๋ฆฌํฐ ํจ์ ๋ฐ ํฌํผ ๋ชจ๋์ ํฌํจํฉ๋๋ค.public/:index.html๊ณผ ๊ฐ์ ์ ์ ์์ฐ์ ๋ณด๊ดํฉ๋๋ค.tests/: ์ ๋ ๋ฐ ํตํฉ ํ ์คํธ๋ฅผ ํฌํจํฉ๋๋ค..eslintrc.js: ESLint๋ฅผ ์ํ ๊ตฌ์ฑ ํ์ผ์ ๋๋ค..prettierrc.js: Prettier๋ฅผ ์ํ ๊ตฌ์ฑ ํ์ผ์ ๋๋ค.webpack.config.js: Webpack์ ์ํ ๊ตฌ์ฑ ํ์ผ์ ๋๋ค.package.json: ํ๋ก์ ํธ ๋ฉํ๋ฐ์ดํฐ์ ์์กด์ฑ์ ํฌํจํฉ๋๋ค.README.md: ํ๋ก์ ํธ๋ฅผ ์ํ ๋ฌธ์์ ๋๋ค.
1.2 ์ ํ๋ก์ ํธ ์ด๊ธฐํ
ํ๋ก์ ํธ๋ฅผ ์ํ ์ ๋๋ ํ ๋ฆฌ๋ฅผ ๋ง๋ค๊ณ npm ๋๋ yarn์ ์ฌ์ฉํ์ฌ package.json ํ์ผ์ ์ด๊ธฐํํ๋ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค:
mkdir my-project cd my-project npm init -y # or yarn init -y
์ด ๋ช
๋ น์ด๋ ๊ธฐ๋ณธ์ ์ธ ํ๋ก์ ํธ ์ ๋ณด๊ฐ ๋ด๊ธด ๊ธฐ๋ณธ package.json ํ์ผ์ ์์ฑํฉ๋๋ค. ์ดํ ์ด ํ์ผ์ ์์ ํ์ฌ ํ๋ก์ ํธ์ ๋ํ ๋ ์์ธํ ์ ๋ณด๋ฅผ ํฌํจํ ์ ์์ต๋๋ค.
2. ํต์ฌ ๊ฐ๋ฐ ๋๊ตฌ
2.1 ํจํค์ง ๋งค๋์ : npm ๋๋ Yarn
ํจํค์ง ๋งค๋์ ๋ ํ๋ก์ ํธ ์์กด์ฑ์ ๊ด๋ฆฌํ๋ ๋ฐ ํ์์ ์ ๋๋ค. npm (Node Package Manager)๊ณผ Yarn์ด ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ์ ํ์ง์ ๋๋ค. npm์ด Node.js์ ๊ธฐ๋ณธ ํจํค์ง ๋งค๋์ ์ด์ง๋ง, Yarn์ ๋ ๋น ๋ฅธ ์ค์น ์๊ฐ๊ณผ ๊ฒฐ์ ๋ก ์ ์์กด์ฑ ํด๊ฒฐ๊ณผ ๊ฐ์ ์ฌ๋ฌ ์ฅ์ ์ ์ ๊ณตํฉ๋๋ค. ์ ํํ๊ธฐ ์ ์ ์ฅ๋จ์ ์ ๊ณ ๋ คํ์ญ์์ค. ๋ ๋ค Linux, MacOS, Windows์ ๊ฐ์ ์์คํ ์์ ์ํํ๊ฒ ์๋ํฉ๋๋ค.
์์กด์ฑ ์ค์น:
# npm npm install react react-dom # yarn yarn add react react-dom
2.2 ํ์คํฌ ๋ฌ๋: npm ์คํฌ๋ฆฝํธ
package.json ํ์ผ์ ์ ์๋ npm ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ๋ฉด ์ผ๋ฐ์ ์ธ ๊ฐ๋ฐ ์์
์ ์๋ํํ ์ ์์ต๋๋ค. ๋ค์์ ๋ช ๊ฐ์ง ์ผ๋ฐ์ ์ธ ์คํฌ๋ฆฝํธ์
๋๋ค:
"scripts": {
"start": "webpack serve --mode development",
"build": "webpack --mode production",
"test": "jest",
"lint": "eslint src/**/*.js",
"format": "prettier --write src/**/*.js"
}
์ค๋ช :
start: Webpack์ ์ฌ์ฉํ์ฌ ๊ฐ๋ฐ ์๋ฒ๋ฅผ ์์ํฉ๋๋ค.build: ํ๋ก๋์ ์ฉ ๋ฒ๋ค์ ๋น๋ํฉ๋๋ค.test: Jest๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ ํ ์คํธ๋ฅผ ์คํํฉ๋๋ค.lint: ESLint๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ ๋ฆฐํธํฉ๋๋ค.format: Prettier๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ ํ์์ ๋ง์ถฅ๋๋ค.
์คํฌ๋ฆฝํธ ์คํ:
# npm npm run start npm run build npm run test # yarn yarn start yarn build yarn test
2.3 ๋ฒ๋ค๋ฌ: Webpack
Webpack์ ์๋ฐ์คํฌ๋ฆฝํธ, CSS ๋ฐ ๊ธฐํ ์์ฐ์ ๋ณํํ๊ณ ํจํค์งํ์ฌ ๋ฐฐํฌํ๋ ๊ฐ๋ ฅํ ๋ชจ๋ ๋ฒ๋ค๋ฌ์ ๋๋ค. ๋ชจ๋์ ์ฝ๋๋ฅผ ์์ฑํ๊ณ ํ๋ก๋์ ์ ์ํด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ต์ ํํ ์ ์๊ฒ ํด์ค๋๋ค.
์ค์น:
npm install webpack webpack-cli webpack-dev-server --save-dev # or yarn add webpack webpack-cli webpack-dev-server --dev
๊ตฌ์ฑ (webpack.config.js):
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 9000,
},
module: {
rules: [
{
test: /\.js$/, // .js ํ์ผ์ ์ฐพ๊ธฐ ์ํด ์ ๊ท์ ์ฌ์ฉ
exclude: /node_modules/, // node_modules ํด๋์ ์ฝ๋๋ ๋ณํํ์ง ์์
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
}
};
์ค๋ช :
entry: ์ ํ๋ฆฌ์ผ์ด์ ์ ์ง์ ์ ์ ๋๋ค.output: ๋ฒ๋ค๋ ์ฝ๋์ ์ถ๋ ฅ ๋๋ ํ ๋ฆฌ ๋ฐ ํ์ผ ์ด๋ฆ์ ๋๋ค.devServer: ๊ฐ๋ฐ ์๋ฒ๋ฅผ ์ํ ๊ตฌ์ฑ์ ๋๋ค.module.rules: ๋ค๋ฅธ ํ์ผ ์ ํ์ด ์ด๋ป๊ฒ ์ฒ๋ฆฌ๋๋์ง๋ฅผ ์ ์ํฉ๋๋ค.
2.4 ํธ๋์คํ์ผ๋ฌ: Babel
Babel์ ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ(ES6+)๋ฅผ ์ด์ ๋ฒ์ ์ ๋ธ๋ผ์ฐ์ ์์ ์คํํ ์ ์๋ ํ์ ํธํ ์ฝ๋๋ก ๋ณํํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํธ๋์คํ์ผ๋ฌ์ ๋๋ค. Babel์ ์ฌ์ฉํ๋ฉด ๊ฐ๋ฐ์๋ ๋ธ๋ผ์ฐ์ ํธํ์ฑ์ ๊ฑฑ์ ํ์ง ์๊ณ ์๋ก์ด ์๋ฐ์คํฌ๋ฆฝํธ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ค์น:
npm install @babel/core @babel/cli @babel/preset-env @babel/preset-react babel-loader --save-dev # or yarn add @babel/core @babel/cli @babel/preset-env @babel/preset-react babel-loader --dev
๊ตฌ์ฑ (babel.config.js ๋๋ webpack.config.js ๋ด๋ถ):
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react']
};
3. ์ฝ๋ ํ์ง ๋ฐ ํฌ๋งทํ
3.1 ๋ฆฐํฐ: ESLint
ESLint๋ ์ฝ๋ฉ ํ์ค์ ๊ฐ์ ํ๊ณ ์ฝ๋์์ ์ ์ฌ์ ์ธ ์ค๋ฅ๋ฅผ ์๋ณํ๋ ๋ฐ ๋์์ด ๋๋ ๋ฆฐํ ๋๊ตฌ์ ๋๋ค. ํ๋ก์ ํธ ์ ๋ฐ์ ๊ฑธ์ณ ์ผ๊ด์ฑ์ ๋ณด์ฅํ๊ณ ์ฝ๋ ํ์ง์ ํฅ์์ํต๋๋ค. ์ฝ๋ฉํ๋ฉด์ ์ฆ๊ฐ์ ์ธ ํผ๋๋ฐฑ์ ๋ฐ๊ธฐ ์ํด IDE์ ํตํฉํ๋ ๊ฒ์ ๊ณ ๋ คํด๋ณด์ธ์. ESLint๋ ํน์ ํ๋ก์ ํธ ๊ฐ์ด๋๋ผ์ธ์ ๊ฐ์ ํ๊ธฐ ์ํ ์ฌ์ฉ์ ์ ์ ๊ท์น ์ธํธ๋ ์ง์ํฉ๋๋ค.
์ค์น:
npm install eslint eslint-plugin-react --save-dev # or yarn add eslint eslint-plugin-react --dev
๊ตฌ์ฑ (.eslintrc.js):
module.exports = {
env: {
browser: true,
es2021: true
},
extends: [
'eslint:recommended',
'plugin:react/recommended'
],
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: 12,
sourceType: 'module'
},
plugins: [
'react'
],
rules: {
'react/prop-types': 'off'
}
};
3.2 ํฌ๋งทํฐ: Prettier
Prettier๋ ์ผ๊ด๋ ์คํ์ผ์ ๋ง์ถฐ ์ฝ๋๋ฅผ ์๋์ผ๋ก ํฌ๋งทํ๋ ๋ ๋จ์ ์ธ(opinionated) ์ฝ๋ ํฌ๋งทํฐ์ ๋๋ค. ์ฝ๋ฉ ์คํ์ผ์ ๋ํ ๋ ผ์์ ์์ ๊ณ ์ฝ๋๋ฒ ์ด์ค๊ฐ ํต์ผ์ฑ ์๊ฒ ๋ณด์ด๋๋ก ๋ณด์ฅํฉ๋๋ค. VSCode ๋ฐ Sublime Text์ ๊ฐ์ ๋ง์ ํธ์ง๊ธฐ๋ ํ์ผ ์ ์ฅ ์ Prettier ํฌ๋งทํ ์ ์๋ํํ๋ ํ๋ฌ๊ทธ์ธ์ ์ ๊ณตํฉ๋๋ค.
์ค์น:
npm install prettier --save-dev # or yarn add prettier --dev
๊ตฌ์ฑ (.prettierrc.js):
module.exports = {
semi: true,
singleQuote: true,
trailingComma: 'es5',
tabWidth: 2,
useTabs: false,
printWidth: 80,
arrowParens: 'always'
};
3.3 ESLint์ Prettier ํตํฉ
ESLint์ Prettier๊ฐ ์ํํ๊ฒ ํจ๊ป ์๋ํ๋๋ก ํ๋ ค๋ฉด ๋ค์ ํจํค์ง๋ฅผ ์ค์นํ์ญ์์ค:
npm install eslint-plugin-prettier eslint-config-prettier --save-dev # or yarn add eslint-plugin-prettier eslint-config-prettier --dev
.eslintrc.js ์
๋ฐ์ดํธ:
module.exports = {
env: {
browser: true,
es2021: true
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:prettier/recommended'
],
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: 12,
sourceType: 'module'
},
plugins: [
'react'
],
rules: {
'react/prop-types': 'off'
}
};
4. ํ ์คํ
4.1 ์ ๋ ํ ์คํ : Jest
Jest๋ ์ ๋ ํ ์คํธ, ํตํฉ ํ ์คํธ, ์๋ํฌ์๋ ํ ์คํธ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์๋ฒฝํ ์๋ฃจ์ ์ ์ ๊ณตํ๋ ์ธ๊ธฐ ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ ์คํ ํ๋ ์์ํฌ์ ๋๋ค. ๋ชจํน(mocking), ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง, ์ค๋ ์ท ํ ์คํ ๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ํฌํจํฉ๋๋ค.
์ค์น:
npm install jest --save-dev # or yarn add jest --dev
๊ตฌ์ฑ (jest.config.js):
module.exports = {
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['/src/setupTests.js'],
moduleNameMapper: {
'\\.(css|less|scss)$': 'identity-obj-proxy',
},
transform: {
'^.+\\.(js|jsx|ts|tsx)$': '/node_modules/babel-jest'
},
};
์์ ํ ์คํธ:
// src/components/Button.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import Button from './Button';
describe('Button Component', () => {
it('renders the button with the correct text', () => {
render();
expect(screen.getByText('Click Me')).toBeInTheDocument();
});
});
4.2 ์๋ํฌ์๋(End-to-End) ํ ์คํ : Cypress
Cypress๋ ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ์ ์ฌ์ฉ์ ์ํธ ์์ฉ์ ์๋ฎฌ๋ ์ด์ ํ๋ ํฌ๊ด์ ์ธ ํ ์คํธ๋ฅผ ์์ฑํ ์ ์๊ฒ ํด์ฃผ๋ ์๋ํฌ์๋ ํ ์คํ ํ๋ ์์ํฌ์ ๋๋ค. ์๊ฐ์ ์ธํฐํ์ด์ค์ ๊ฐ๋ ฅํ ๋๋ฒ๊น ๋๊ตฌ๋ฅผ ์ ๊ณตํฉ๋๋ค. Cypress๋ ๋ณต์กํ ์ฌ์ฉ์ ํ๋ฆ๊ณผ ์ํธ ์์ฉ์ ํ ์คํธํ๋ ๋ฐ ํนํ ์ ์ฉํฉ๋๋ค.
์ค์น:
npm install cypress --save-dev # or yarn add cypress --dev
์์ ํ ์คํธ:
// cypress/integration/example.spec.js
describe('๋์ ์ฒซ ํ
์คํธ', () => {
it('Kitchen Sink ์ฌ์ดํธ๋ฅผ ๋ฐฉ๋ฌธํฉ๋๋ค', () => {
cy.visit('https://example.cypress.io');
cy.contains('type').click();
cy.url().should('include', '/commands/actions');
cy.get('.action-email')
.type('fake@email.com')
.should('have.value', 'fake@email.com');
});
});
5. ์ง์์ ์ธ ํตํฉ ๋ฐ ์ง์์ ์ธ ์ ๋ฌ (CI/CD)
5.1 CI/CD ํ์ดํ๋ผ์ธ ์ค์
CI/CD๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋น๋, ํ ์คํธ, ๋ฐฐํฌ ํ๋ก์ธ์ค๋ฅผ ์๋ํํ์ฌ ๋น ๋ฅด๊ณ ์์ ์ ์ธ ๋ฆด๋ฆฌ์ค๋ฅผ ๋ณด์ฅํฉ๋๋ค. ์ธ๊ธฐ ์๋ CI/CD ํ๋ซํผ์ผ๋ก๋ GitHub Actions, Jenkins, CircleCI, GitLab CI๊ฐ ์์ต๋๋ค. ๋จ๊ณ์๋ ์ผ๋ฐ์ ์ผ๋ก ๋ฆฐํ , ํ ์คํธ ์คํ, ํ๋ก๋์ ์ฉ ์์ฐ ๋น๋๊ฐ ํฌํจ๋ฉ๋๋ค.
GitHub Actions ์ฌ์ฉ ์์ (.github/workflows/main.yml):
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Node.js ์ค์
uses: actions/setup-node@v2
with:
node-version: '16'
- name: ์์กด์ฑ ์ค์น
run: npm install
- name: ESLint ์คํ
run: npm run lint
- name: ํ
์คํธ ์คํ
run: npm run test
- name: ๋น๋
run: npm run build
5.2 ๋ฐฐํฌ ์ ๋ต
๋ฐฐํฌ ์ ๋ต์ ํธ์คํ ํ๊ฒฝ์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. ์ต์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ์ ์ ์ฌ์ดํธ ํธ์คํ : Netlify, Vercel ๋๋ AWS S3์ ๊ฐ์ ํ๋ซํผ์ ์ ์ ์์ฐ์ ๋ฐฐํฌํฉ๋๋ค.
- ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง (SSR): Heroku, AWS EC2 ๋๋ Google Cloud Platform๊ณผ ๊ฐ์ ํ๋ซํผ์ ๋ฐฐํฌํฉ๋๋ค.
- ์ปจํ ์ด๋ํ: Docker์ Kubernetes์ ๊ฐ์ ์ปจํ ์ด๋ ์ค์ผ์คํธ๋ ์ด์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
6. ์ฑ๋ฅ ์ต์ ํ
6.1 ์ฝ๋ ๋ถํ (Code Splitting)
์ฝ๋ ๋ถํ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ ์์ ์ฒญํฌ๋ก ๋๋์ด ๋ธ๋ผ์ฐ์ ๊ฐ ํ์ฌ ๋ทฐ์ ํ์ํ ์ฝ๋๋ง ๋ค์ด๋ก๋ํ ์ ์๋๋ก ํ๋ ๊ฒ์ ๋๋ค. ์ด๋ ์ด๊ธฐ ๋ก๋ ์๊ฐ์ ์ค์ด๊ณ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. Webpack์ ๋์ import๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋ ๋ถํ ์ ์ง์ํฉ๋๋ค:
import('./components/MyComponent')
.then(module => {
const MyComponent = module.default;
// MyComponent ์ฌ์ฉ
})
.catch(error => {
console.error('์ปดํฌ๋ํธ ๋ก๋ฉ ์คํจ', error);
});
6.2 ์ง์ฐ ๋ก๋ฉ(Lazy Loading)
์ง์ฐ ๋ก๋ฉ์ ์ค์ํ์ง ์์ ๋ฆฌ์์ค์ ๋ก๋ฉ์ ํ์ํ ๋๊น์ง ์ง์ฐ์ํค๋ ๊ฒ์ ๋๋ค. ์ด๋ ์ด๊ธฐ ๋ก๋ ์๊ฐ์ ์ค์ด๊ณ ์ฒด๊ฐ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. ์ด๋ฏธ์ง์ ์ปดํฌ๋ํธ๋ Intersection Observer์ ๊ฐ์ ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ์ง์ฐ ๋ก๋ฉ๋ ์ ์์ต๋๋ค.
6.3 ํธ๋ฆฌ ์์ดํน(Tree Shaking)
ํธ๋ฆฌ ์์ดํน์ ๋น๋ ํ๋ก์ธ์ค ์ค์ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉ๋์ง ์๋ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๋ ๊ธฐ์ ์ ๋๋ค. ์ด๋ ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. Webpack์ ์ฝ๋์ import ๋ฐ export ๋ฌธ์ ๋ถ์ํ์ฌ ํธ๋ฆฌ ์์ดํน์ ์ง์ํฉ๋๋ค.
6.4 ์ด๋ฏธ์ง ์ต์ ํ
์ด๋ฏธ์ง ์ต์ ํ๋ ํ์ง ์ ํ ์์ด ํ์ผ ํฌ๊ธฐ๋ฅผ ์ค์ด๊ธฐ ์ํด ์ด๋ฏธ์ง๋ฅผ ์์ถํ๊ณ ํฌ๊ธฐ๋ฅผ ์กฐ์ ํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ImageOptim ๋ฐ TinyPNG์ ๊ฐ์ ๋๊ตฌ๋ ์ด ํ๋ก์ธ์ค๋ฅผ ์๋ํํ ์ ์์ต๋๋ค. WebP์ ๊ฐ์ ์ต์ ์ด๋ฏธ์ง ํ์์ ์ฌ์ฉํ๋ฉด ์์ถ๋ฅ ๊ณผ ์ฑ๋ฅ์ ํฅ์์ํฌ ์๋ ์์ต๋๋ค.
7. ๋ฒ์ ๊ด๋ฆฌ: Git
Git์ ์ฝ๋๋ฒ ์ด์ค์ ๋ณ๊ฒฝ ์ฌํญ์ ์ถ์ ํ๊ณ ๋ค๋ฅธ ๊ฐ๋ฐ์์ ํ์ ํ๊ธฐ ์ํ ํ์์ ์ธ ๋ฒ์ ๊ด๋ฆฌ ์์คํ ์ ๋๋ค. GitHub, GitLab ๋๋ Bitbucket๊ณผ ๊ฐ์ ํธ์คํ ๋ Git ์ ์ฅ์๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํ ์ค์ ์ง์ค์ ํ๋ซํผ์ ์ ๊ณตํฉ๋๋ค.
7.1 Git ์ ์ฅ์ ์ค์
ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ์์ ์ Git ์ ์ฅ์๋ฅผ ์ด๊ธฐํํฉ๋๋ค:
git init
ํ์ผ์ ์คํ ์ด์ง ์์ญ์ ์ถ๊ฐํ๊ณ ๋ณ๊ฒฝ ์ฌํญ์ ์ปค๋ฐํฉ๋๋ค:
git add . git commit -m "์ด๊ธฐ ์ปค๋ฐ"
GitHub, GitLab ๋๋ Bitbucket์ ์ ์ ์ฅ์๋ฅผ ๋ง๋ค๊ณ ๋ก์ปฌ ์ ์ฅ์๋ฅผ ์๊ฒฉ ์ ์ฅ์๋ก ํธ์ํฉ๋๋ค:
git remote add origin [์๊ฒฉ ์ ์ฅ์ URL] git push -u origin main
7.2 ๋ธ๋์นญ ์ ๋ต
๋ธ๋์นญ์ ์ฌ์ฉํ๋ฉด ์ฃผ ์ฝ๋๋ฒ ์ด์ค์ ์ํฅ์ ์ฃผ์ง ์๊ณ ์๋ก์ด ๊ธฐ๋ฅ์ด๋ ๋ฒ๊ทธ ์์ ์์ ์ ๋ ๋ฆฝ์ ์ผ๋ก ์ํํ ์ ์์ต๋๋ค. ์ธ๊ธฐ ์๋ ๋ธ๋์นญ ์ ๋ต์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- Gitflow: ์ฌ๋ฌ ๋ธ๋์น(์:
main,develop,feature,release,hotfix)๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋ฐ์ ์ฌ๋ฌ ๋จ๊ณ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. - GitHub Flow: ๋จ์ผ
main๋ธ๋์น๋ฅผ ์ฌ์ฉํ๊ณ ๊ฐ ์๋ก์ด ๊ธฐ๋ฅ์ด๋ ๋ฒ๊ทธ ์์ ์ ๋ํด ํผ์ฒ ๋ธ๋์น๋ฅผ ์์ฑํฉ๋๋ค. - GitLab Flow: GitHub Flow์ ํ์ฅ์ผ๋ก, ๋ค๋ฅธ ํ๊ฒฝ์ผ๋ก์ ๋ฐฐํฌ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ํ๊ฒฝ ๋ธ๋์น(์:
production,staging)๋ฅผ ํฌํจํฉ๋๋ค.
8. ๋ฌธ์ํ ๋ฐ ํ์
8.1 ๋ฌธ์ ์์ฑ
์๋ํ๋ ๋ฌธ์ ์์ฑ ๋๊ตฌ๋ ์ฝ๋ ์ฃผ์์์ ๋ฌธ์๋ฅผ ์ถ์ถํ ์ ์์ต๋๋ค. JSDoc์ด ์ธ๊ธฐ ์๋ ์ต์ ์ ๋๋ค. ๋ฌธ์ ์์ฑ์ CI/CD ํ์ดํ๋ผ์ธ์ ํตํฉํ๋ฉด ๋ฌธ์๊ฐ ํญ์ ์ต์ ์ํ๋ก ์ ์ง๋ฉ๋๋ค.
8.2 ํ์ ๋๊ตฌ
Slack, Microsoft Teams, Jira์ ๊ฐ์ ๋๊ตฌ๋ ํ์ ๊ฐ์ ์ํต๊ณผ ํ์ ์ ์ด์งํฉ๋๋ค. ์ด๋ฌํ ๋๊ตฌ๋ ์ปค๋ฎค๋์ผ์ด์ ์ ๊ฐ์ํํ๊ณ , ์ํฌํ๋ก์ฐ๋ฅผ ๊ฐ์ ํ๋ฉฐ, ์ ๋ฐ์ ์ธ ์์ฐ์ฑ์ ํฅ์์ํต๋๋ค.
9. ๋ณด์ ๊ณ ๋ ค์ฌํญ
9.1 ์์กด์ฑ ์ทจ์ฝ์
npm audit ๋๋ Yarn audit๊ณผ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ก์ ํธ ์์กด์ฑ์์ ์๋ ค์ง ์ทจ์ฝ์ ์ ์ ๊ธฐ์ ์ผ๋ก ์ค์บํ์ญ์์ค. ์ทจ์ฝ์ ์ ์ ์ํ๊ฒ ํจ์นํ๊ธฐ ์ํด ์์กด์ฑ ์ ๋ฐ์ดํธ๋ฅผ ์๋ํํ์ญ์์ค.
9.2 ๋น๋ฐ ์ ๋ณด ๊ด๋ฆฌ
API ํค, ์ํธ ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๊ฒฉ ์ฆ๋ช ๊ณผ ๊ฐ์ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ Git ์ ์ฅ์์ ์ ๋๋ก ์ปค๋ฐํ์ง ๋ง์ญ์์ค. ํ๊ฒฝ ๋ณ์๋ ๋น๋ฐ ์ ๋ณด ๊ด๋ฆฌ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ์์ ํ๊ฒ ์ ์ฅํ๊ณ ๊ด๋ฆฌํ์ญ์์ค. HashiCorp Vault์ ๊ฐ์ ๋๊ตฌ๊ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
9.3 ์ ๋ ฅ ์ ํจ์ฑ ๊ฒ์ฌ ๋ฐ ์ด๊ท (Sanitization)
๊ต์ฐจ ์ฌ์ดํธ ์คํฌ๋ฆฝํ (XSS) ๋ฐ SQL ์ฝ์ ๊ณผ ๊ฐ์ ๋ณด์ ์ทจ์ฝ์ ์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ฌ์ฉ์ ์ ๋ ฅ์ ๊ฒ์ฆํ๊ณ ์ด๊ท ํ์ญ์์ค. ์ ๋ ฅ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ํด validator.js์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ณ HTML ์ด๊ท ์ ์ํด DOMPurify๋ฅผ ์ฌ์ฉํ์ญ์์ค.
10. ๋ชจ๋ํฐ๋ง ๋ฐ ๋ถ์
10.1 ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง (APM)
New Relic, Datadog, Sentry์ ๊ฐ์ APM ๋๊ตฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ ๋ํ ์ค์๊ฐ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํ๊ณ ์ ์ฌ์ ์ธ ๋ณ๋ชฉ ํ์์ ์๋ณํฉ๋๋ค. ์ด๋ฌํ ๋๊ตฌ๋ ์๋ต ์๊ฐ, ์ค๋ฅ์จ, ๋ฆฌ์์ค ์ฌ์ฉ๋ฅ ๊ณผ ๊ฐ์ ๋ฉํธ๋ฆญ์ ๋ชจ๋ํฐ๋งํฉ๋๋ค.
10.2 ๋ถ์ ๋๊ตฌ
Google Analytics, Mixpanel, Amplitude์ ๊ฐ์ ๋ถ์ ๋๊ตฌ๋ ์ฌ์ฉ์ ํ๋์ ์ถ์ ํ๊ณ ์ฌ์ฉ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ์ด๋ป๊ฒ ์ํธ ์์ฉํ๋์ง์ ๋ํ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ฌํ ๋๊ตฌ๋ ์ฌ์ฉ์ ์ ํธ๋๋ฅผ ์ดํดํ๊ณ , ๊ฐ์ ์์ญ์ ์๋ณํ๋ฉฐ, ๋ ๋์ ์ฐธ์ฌ๋ฅผ ์ํด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ต์ ํํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
11. ํ์งํ(l10n) ๋ฐ ๊ตญ์ ํ(i18n)
๊ธ๋ก๋ฒ ๊ณ ๊ฐ์ ์ํ ์ ํ์ ๋ง๋ค ๋ ํ์งํ(l10n)์ ๊ตญ์ ํ(i18n)๋ฅผ ๊ณ ๋ คํ๋ ๊ฒ์ด ํ์์ ์ ๋๋ค. ์ด๋ ์ฌ๋ฌ ์ธ์ด, ํตํ, ๋ฌธํ์ ๊ด์ต์ ์ง์ํ๋๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ์ค๊ณํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค.
11.1 i18n ๊ตฌํ
i18next ๋๋ react-intl๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฒ์ญ์ ๊ด๋ฆฌํ๊ณ ์ฌ์ฉ์์ ๋ก์ผ์ผ์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฅผ ํฌ๋งทํ์ญ์์ค. ๋ฒ์ญ์ ๋ณ๋์ ํ์ผ์ ์ ์ฅํ๊ณ ์ฌ์ฉ์์ ์ธ์ด ์ค์ ์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๋ก๋ํ์ญ์์ค.
11.2 ๋ค์ค ํตํ ์ง์
ํตํ ํฌ๋งทํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์ ํ์ง ํตํ๋ก ๊ฐ๊ฒฉ์ ํ์ํ์ญ์์ค. ๋ค์ค ํตํ๋ฅผ ์ง์ํ๋ ๊ฒฐ์ ๊ฒ์ดํธ์จ์ด์ ํตํฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค.
11.3 ๋ ์ง ๋ฐ ์๊ฐ ํ์ ์ฒ๋ฆฌ
๋ ์ง ๋ฐ ์๊ฐ ํฌ๋งทํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์ ํ์ง ํ์์ผ๋ก ๋ ์ง์ ์๊ฐ์ ํ์ํ์ญ์์ค. ์ฌ์ฉ์์ ์์น์ ๊ด๊ณ์์ด ์๊ฐ์ด ์ฌ๋ฐ๋ฅด๊ฒ ํ์๋๋๋ก ์๊ฐ๋ ์ฒ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ญ์์ค. Moment.js์ date-fns๊ฐ ์ผ๋ฐ์ ์ธ ์ ํ์ด์ง๋ง, ๋ ์์ ํฌ๊ธฐ์ ๋ชจ๋์ ๋์์ธ์ผ๋ก ์ธํด ์ต์ ํ๋ก์ ํธ์์๋ ์ผ๋ฐ์ ์ผ๋ก date-fns๊ฐ ๊ถ์ฅ๋ฉ๋๋ค.
12. ์ ๊ทผ์ฑ
์ ๊ทผ์ฑ์ ์ฅ์ ๊ฐ ์๋ ์ฌ๋๋ค์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉํ ์ ์๋๋ก ๋ณด์ฅํฉ๋๋ค. ์น ์ ๊ทผ์ฑ ํ์ค(WCAG)์ ์ค์ํ๊ณ ์ด๋ฏธ์ง์ ๋ํ ๋์ฒด ํ ์คํธ, ํค๋ณด๋ ๋ด๋น๊ฒ์ด์ , ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ง์์ ์ ๊ณตํ์ญ์์ค. axe-core์ ๊ฐ์ ํ ์คํธ ๋๊ตฌ๋ ์ ๊ทผ์ฑ ๋ฌธ์ ๋ฅผ ์๋ณํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
13. ๊ฒฐ๋ก
๊ฒฌ๊ณ ํ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ์ธํ๋ผ๋ฅผ ๊ตฌ์ถํ๋ ๊ฒ์ ์ ์คํ ๊ณํ๊ณผ ์ ์ ํ ๋๊ตฌ ์ ํ์ ํฌํจํฉ๋๋ค. ์ด ๊ฐ์ด๋์์ ์ค๋ช ํ ์ ๋ต์ ๊ตฌํํจ์ผ๋ก์จ ํ๋ก์ ํธ์ ์ฅ๊ธฐ์ ์ธ ์ฑ๊ณต์ ์ง์ํ๋ ํจ์จ์ ์ด๊ณ ์ ๋ขฐํ ์ ์์ผ๋ฉฐ ํ์ฅ ๊ฐ๋ฅํ ๊ฐ๋ฐ ํ๊ฒฝ์ ๋ง๋ค ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ ์ฝ๋ ํ์ง, ํ ์คํ , ์๋ํ, ๋ณด์ ๋ฐ ์ฑ๋ฅ ์ต์ ํ์ ๋ํ ์ ์คํ ๊ณ ๋ ค๊ฐ ํฌํจ๋ฉ๋๋ค. ๊ฐ ํ๋ก์ ํธ๋ ์๋ก ๋ค๋ฅธ ์๊ตฌ ์ฌํญ์ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก ํญ์ ์ธํ๋ผ๋ฅผ ํด๋น ์๊ตฌ ์ฌํญ์ ๋ง๊ฒ ์กฐ์ ํ์ญ์์ค.
๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์์ฉํ๊ณ ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ๋ฅผ ์ง์์ ์ผ๋ก ๊ฐ์ ํจ์ผ๋ก์จ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ก์ ํธ๊ฐ ์ ๊ตฌ์กฐํ๋๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ๋ฉฐ ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ๋ฐ์ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ๋๋ก ๋ณด์ฅํ ์ ์์ต๋๋ค. ์ธํ๋ผ๋ฅผ ์ง์์ ์ผ๋ก ๊ฐ์ ํ๊ณ ํฅ์์ํค๊ธฐ ์ํด ๊ฐ๋ฐ ํ๋ก์ธ์ค ์ ๋ฐ์ ๊ฑธ์ณ ์ฌ์ฉ์ ํผ๋๋ฐฑ ๋ฃจํ๋ฅผ ํตํฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค.